home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 15 / BBS in a box XV-2.iso / Files II / Prog / M / MacPerl 4.13 source.sit / Perl Source ƒ / MacPerl / MPUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-04  |  24.3 KB  |  1,007 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPEditUtils.c    -
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPUtils.c,v $
  12. Revision 1.2  1994/05/04  02:52:40  neeri
  13. Inline Input.
  14.  
  15. Revision 1.1  1994/02/27  23:02:08  neeri
  16. Initial revision
  17.  
  18. Revision 0.5  1993/08/17  00:00:00  neeri
  19. DoPrefDialog()
  20.  
  21. Revision 0.4  1993/08/15  00:00:00  neeri
  22. DoAbout
  23.  
  24. Revision 0.3  1993/08/14  00:00:00  neeri
  25. Preference file
  26.  
  27. Revision 0.2  1993/05/30  00:00:00  neeri
  28. Support Console Windows
  29.  
  30. Revision 0.1  1993/05/29  00:00:00  neeri
  31. Compiles correctly
  32.  
  33. *********************************************************************/
  34.  
  35. #include <PLStringFuncs.h>
  36. #include <Events.h>
  37. #include <Traps.h>
  38. #include <Dialogs.h>
  39. #include <Fonts.h>
  40. #include <Packages.h>
  41. #include <ToolUtils.h>
  42. #include <AppleEvents.h>
  43. #include <TFileSpec.h>
  44. #include <Folders.h>
  45. #include <Resources.h>
  46. #include <OSUtils.h>
  47. #include <Files.h>
  48. #include <Lists.h>
  49. #include <Icons.h>
  50. #include <TSMTE.h>
  51. #include <string.h>
  52. #include <GUSI.h>
  53. #include <Desk.h>
  54. #include <ctype.h>
  55. #include <stdio.h>
  56.  
  57. #include "MPUtils.h"
  58. #include "MPWindow.h"
  59. #include <patchlevel.h>
  60.  
  61. /**-----------------------------------------------------------------------
  62.         Name:         ShowError
  63.         Purpose:        Reports an error to the user as both string and number.
  64.     -----------------------------------------------------------------------**/
  65. #pragma segment Utils
  66.  
  67. pascal void ShowError(Str255 theError, long theErrorCode)
  68. {
  69.     short     alertResult;
  70.     Str255    theString;
  71.  
  72.     if (gAppleEventsImplemented)
  73.         if (AEInteractWithUser(kAEDefaultTimeout, nil,nil))
  74.             return;
  75.         
  76.      SetCursor(&qd.arrow);
  77.      NumToString(theErrorCode, theString);
  78.      ParamText(theError, theString, "", "");
  79.      alertResult = Alert(300, nil);
  80. } /* ShowError */
  81.  
  82. /**-----------------------------------------------------------------------
  83.         Name:         Ours
  84.         Purpose:        Checks the frontmost window belongs to the app.
  85.     -----------------------------------------------------------------------**/
  86. #pragma segment Utils
  87.  
  88. pascal Boolean Ours(WindowPtr aWindow)
  89. {
  90.     if (aWindow)
  91.         if (((WindowPeek)aWindow)->windowKind == zoomDocProc)
  92.             return(true);
  93.  
  94.     return(false);
  95. } /* Ours */
  96.  
  97. /**-----------------------------------------------------------------------
  98.         Name:         SetShortMenus
  99.         Purpose:        Cuts the menus down to a minimum - Apple File Edit.
  100.                         Greys out the unavailable options - used when no docs open
  101.     -----------------------------------------------------------------------**/
  102. #pragma segment Utils
  103.  
  104. pascal void SetShortMenus()
  105. {
  106.     DeleteMenu(windowID);
  107.     
  108.     DisableItem(myMenus[fileM], fmClose);
  109.     DisableItem(myMenus[fileM], fmSave);
  110.     DisableItem(myMenus[fileM], fmSaveAs);
  111.     DisableItem(myMenus[fileM], fmRevert);
  112.     DisableItem(myMenus[fileM], fmPrint);
  113.     DisableItem(myMenus[fileM], fmPageSetUp);
  114.  
  115.     /* now the unnecessary items on the edit menu */
  116.  
  117.     DisableItem(myMenus[editM], undoCommand);
  118.     DisableItem(myMenus[editM], cutCommand);
  119.     DisableItem(myMenus[editM], copyCommand);
  120.     DisableItem(myMenus[editM], clearCommand);
  121.     DisableItem(myMenus[editM], pasteCommand);
  122.     DisableItem(myMenus[editM], selectAllCommand);
  123.  
  124.     DrawMenuBar();
  125. }  /* SetShortMenus */
  126.  
  127. /**-----------------------------------------------------------------------
  128.         Name:         SetLongMenus
  129.         Purpose:        Reinstates the full menu bar - called when first document
  130.                     opened.
  131.     -----------------------------------------------------------------------**/
  132. #pragma segment Utils
  133.  
  134. pascal void SetLongMenus()
  135. {
  136.     InsertMenu(myMenus[windowM], perlID);
  137.     
  138.     EnableItem(myMenus[fileM], fmClose);
  139.     EnableItem(myMenus[fileM], fmSave);
  140.     EnableItem(myMenus[fileM], fmSaveAs);
  141.     EnableItem(myMenus[fileM], fmRevert);
  142.     EnableItem(myMenus[fileM], fmPrint);
  143.     EnableItem(myMenus[fileM], fmPageSetUp);
  144.  
  145.     /* now the necessary items on the edit menu -
  146.         many other items fixed on each pass thru the main event
  147.         loop or before the window pulled down
  148.     */
  149.  
  150.     EnableItem(myMenus[editM], selectAllCommand);
  151.  
  152.     DrawMenuBar();
  153. }  /* SetLongMenus */
  154.  
  155. /**-----------------------------------------------------------------------
  156.     Name:       SetEditMenu
  157.     Purpose:    Set the text of the edit menu according to the state of
  158.                      current document.
  159.   -----------------------------------------------------------------------**/
  160.  
  161. #pragma segment Utils
  162.  
  163. pascal void SetEditMenu(DPtr theDoc)
  164. {
  165. #ifndef RUNTIME
  166.     if (theDoc->kind == kDocumentWindow && theDoc->u.reg.showBorders)
  167.         SetItem(myMenus[editM], cBorders, "\pHide Borders");
  168.     else
  169.         SetItem(myMenus[editM], cBorders, "\pShow Borders");
  170. #endif
  171. }  /* SetEditMenu */
  172.  
  173. /**-----------------------------------------------------------------------
  174.     Name:       GetTempFileName
  175.     Purpose:    Fills newstring with a temporary file name.
  176.   -----------------------------------------------------------------------**/
  177.  
  178. #pragma segment Utils
  179.  
  180. pascal void GetTempFileName(DPtr aDoc, Str255 newString)
  181. {
  182.     Str255        s;
  183.     Str255        fileName;
  184.  
  185.     if (aDoc->kind != kDocumentWindow || aDoc->u.reg.everSaved == false)
  186.         PLstrcpy(fileName, "\pMacPerlTmp");
  187.     else
  188.         PLstrcpy(fileName, aDoc->theFileName);
  189.  
  190.     /*generate a unique(ish) temporary filename*/
  191.  
  192.     if (fileName[0] > 21)
  193.         fileName[0] = 21;
  194.  
  195.     NumToString(TickCount(), s);
  196.  
  197.     PLstrcat(fileName, s);
  198.  
  199.     PLstrcpy(newString,fileName);
  200. }
  201.  
  202. /**-----------------------------------------------------------------------
  203.     Name:       SetText
  204.     Purpose:    Sets the text of the supplied itemNo in aDialog to
  205.                     theString and select it.
  206.   -----------------------------------------------------------------------**/
  207.  
  208. #pragma segment Utils
  209.  
  210. pascal void SetText(DialogPtr aDialog, short itemNo, Str255 theString)
  211. {
  212.     Handle      itemHandle;
  213.     Rect        box;
  214.     short       kind;
  215.     TEHandle    theTEHandle;
  216.  
  217.     GetDItem(aDialog, itemNo, &kind, &itemHandle, &box);
  218.     SetIText(itemHandle, theString);
  219.  
  220.     theTEHandle = ((DialogPeek)aDialog)->textH;
  221.  
  222.     /*set all the text to be selected*/
  223.     if (theTEHandle)
  224.         TESetSelect(0, 255, theTEHandle);
  225. }
  226.  
  227. /**-----------------------------------------------------------------------
  228.     Name:       RetrieveText
  229.     Purpose:    Returns the text of anItem in aDialog in aString.
  230.   -----------------------------------------------------------------------**/
  231.  
  232. #pragma segment Utils
  233.  
  234. pascal void RetrieveText(DialogPtr aDialog, short anItem, Str255 aString)
  235. {
  236.     short      kind;
  237.     Rect       box;
  238.     Handle     itemHandle;
  239.  
  240.     GetDItem(aDialog, anItem, &kind, &itemHandle, &box);
  241.     GetIText(itemHandle, aString);
  242. }
  243.  
  244. /**-----------------------------------------------------------------------
  245.     Name:      DrawDefaultOutline
  246.     Purpose:   Draws an outline around theItem.
  247.                     Called as a useritem Proc by the dialog manager.
  248.                     To use place a useritem over the default item in the
  249.                     dialog and install the address of this proc as the item
  250.                     handle.
  251.   -----------------------------------------------------------------------**/
  252.  
  253. #pragma segment Utils
  254.  
  255. pascal void DrawDefaultOutline(DialogPtr theDialog, short theItem)
  256. {
  257.     short       kind;
  258.     Handle      itemHandle;
  259.     Rect        box;
  260.  
  261.     GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  262.     PenSize(3, 3);
  263.     InsetRect(&box, -4, -4);
  264.     FrameRoundRect(&box, 16, 16);
  265.     PenNormal();
  266. }  /* DrawDefaultOutline */
  267.  
  268. /**-----------------------------------------------------------------------
  269.     Name:       AdornDefaultButton
  270.     Purpose:    Installs DrawDefaultOutline as the useritem proc
  271.                      for the given item.
  272. -----------------------------------------------------------------------**/
  273.  
  274. #pragma segment Utils
  275.  
  276. pascal void AdornDefaultButton(DialogPtr theDialog,short theItem)
  277. {
  278.     short        kind;
  279.     Handle    itemHandle;
  280.      Rect        box;
  281.  
  282.     GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  283.     SetDItem(theDialog, theItem, kind, (Handle)&DrawDefaultOutline, &box);
  284. }
  285.  
  286. pascal void GetRectOfDialogItem(DialogPtr theDialog, short theItem, Rect *theRect)
  287. {
  288.     short       kind;
  289.     Handle      itemHandle;
  290.  
  291.     GetDItem(theDialog, theItem, &kind, &itemHandle, theRect);
  292. }
  293.  
  294. /**------  FeatureIsImplemented    ------------**/
  295. /*    This is called to use Gestalt to determine if a feature is implemented.
  296.      This applies to only those referenced by OSType    */
  297.  
  298. #pragma segment Utils
  299.  
  300. pascal Boolean FeatureIsImplemented(OSType theFeature, short theTestBit)
  301. {
  302.      long      result;
  303.  
  304.     return !Gestalt(theFeature, &result) && (result & (1 << theTestBit));
  305. }
  306.  
  307. #pragma segment Utils
  308.  
  309. pascal Boolean CheckEnvironment()
  310. {
  311.     long result;
  312.     
  313.     /*check for the AppleEvents manager - we certainly can't work without it*/
  314.  
  315.     gAppleEventsImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr, gestaltAppleEventsPresent);
  316.  
  317. #ifndef RUNTIME
  318.     /*first check if the Edition Manager is present*/
  319.  
  320.     gEditionManagerImplemented = FeatureIsImplemented(gestaltEditionMgrAttr, gestaltEditionMgrPresent);
  321.  
  322.     /*and for good measure- the Alias manager*/
  323.  
  324.     gAliasManagerImplemented  = FeatureIsImplemented(gestaltAliasMgrAttr, gestaltAliasMgrPresent);
  325.  
  326.     /*check if recording is implemented*/
  327.  
  328.     gRecordingImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr,1);
  329.  
  330.     /*check for the Outline fonts*/
  331.  
  332.     gOutlineFontsImplemented  = FeatureIsImplemented(gestaltFontMgrAttr, gestaltOutlineFonts);
  333.  
  334.     /* check for Text Services and TSMTE */
  335.     gTextServicesImplemented = !Gestalt(gestaltTSMgrVersion, &result) && (result > 0);
  336.     gTSMTEImplemented    = FeatureIsImplemented(gestaltTSMTEAttr, gestaltTSMTEPresent);
  337.  
  338.     return     gEditionManagerImplemented &&
  339.                 gAliasManagerImplemented   &&
  340.                 gAppleEventsImplemented    &&
  341.                 gOutlineFontsImplemented;
  342. #else
  343.     return true;
  344. #endif
  345. }  /* CheckEnvironment */
  346.  
  347. /*
  348.     DoPageSetup returns true if the page setup of the document is altered
  349. */
  350.  
  351. pascal Boolean DoPageSetup(DPtr theDoc)
  352. {
  353.     if (theDoc) {
  354.         Boolean result;
  355.  
  356.         PrOpen();
  357.         result =  PrStlDialog(theDoc->thePrintSetup);
  358.         PrClose();
  359.  
  360.         return(result);
  361.     }
  362. }  /* DoPageSetup */
  363.  
  364. /*
  365.     Name:    CtrlKeyPressed
  366.     Purpose: Returns true if control key pressed during event
  367. */
  368. pascal Boolean CtrlKeyPressed(const EventRecord *theEvent)
  369. {
  370.     return theEvent->modifiers & controlKey;
  371. }
  372.  
  373. /*
  374.     Name:    OptionKeyPressed
  375.     Purpose: Returns true if option key pressed during event
  376. */
  377. pascal Boolean OptionKeyPressed(const EventRecord *theEvent)
  378. {
  379.     return theEvent->modifiers & optionKey;
  380. }
  381.  
  382. pascal void DrawVersion(DialogPtr dlg, short item)
  383. {
  384.     VersRecHndl    vers;
  385.     short            base;
  386.     Handle        h;
  387.     Rect            r;
  388.     FontInfo        info;
  389.     Str15            patchlevel;
  390.  
  391.     GetDItem(dlg, item, &base, &h, &r);
  392.     SetPort(dlg);
  393.     TextFont(1);
  394.     TextSize(10);
  395.     GetFontInfo(&info);
  396.     
  397.     base = r.top+2+info.ascent;
  398.     MoveTo(r.left+2, base);
  399.     DrawString("\pVersion");
  400.     MoveTo((r.left+r.right) >> 1, r.top+2+info.ascent);
  401.     
  402.     vers = (VersRecHndl) GetResource('vers', 1);
  403.     HLock((Handle) vers);
  404.     DrawString((*vers)->shortVersion);
  405.     ReleaseResource((Handle) vers);
  406.  
  407.     base += info.ascent + info.descent + info.leading;
  408.     MoveTo(r.left+2, base);
  409.     DrawString("\pPatchlevel");
  410.     MoveTo((r.left+r.right) >> 1, base);
  411.     patchlevel[0] = sprintf((char *) patchlevel+1, "%d", PATCHLEVEL);
  412.     DrawString(patchlevel);
  413.  
  414.     TextFont(CreditID);
  415.     TextSize(12);
  416. }
  417.  
  418. pascal void DoAbout()
  419. {
  420.     DialogPtr    dlg;
  421.     short            kind;
  422.     Handle        hdl;
  423.     Rect            bounds;
  424.     Rect             hot;
  425.     Str255        string;
  426.     short *        widths;
  427.     short            count;
  428.     short            current;
  429.     short            offset;
  430.     EventRecord    ev;
  431.     RgnHandle    rgn;
  432.     long            lastTicks;
  433.     
  434.     SetCursor(&qd.arrow);
  435.     
  436.     dlg = GetNewDialog(AboutDialog, nil, (WindowPtr) -1);
  437.  
  438.     GetDItem(dlg, 2, &kind, &hdl, &bounds);
  439.     SetDItem(dlg, 2, kind, (Handle) DrawVersion, &bounds);
  440.     
  441.     DrawDialog(dlg);
  442. #ifndef RUNTIME
  443.     GetDItem(dlg, 1, &kind, &hdl, &bounds);
  444.     SetPort(dlg);
  445.     TextFont(CreditID);
  446.     TextSize(12);
  447.     TextFace(normal);
  448.     ClipRect(&bounds);
  449.     hot         =     bounds;
  450.     hot.left    =    hot.right-2;
  451.     
  452.     kind         = StringWidth("\p • ");
  453.     hdl         = GetResource('STR#', CreditID);
  454.     count        = **(short **) hdl;
  455.     widths     = (short *) NewPtr(2 * count);
  456.     
  457.     for (current = 0; current<count; ++current) {
  458.         GetIndString(string, CreditID, current+1);
  459.         widths[current] = StringWidth(string) + kind;
  460.     }
  461.     
  462.     offset     =     0;
  463.     current     =     0;
  464.     rgn        =    NewRgn();
  465.     lastTicks=    0;
  466.     GetIndString(string, CreditID, current+1);
  467. #endif
  468.  
  469.     while (dlg) {
  470. #ifndef RUNTIME
  471.         while (TickCount() < lastTicks + 2);
  472.         
  473.         lastTicks = TickCount();
  474.         
  475.         SetPort(dlg);
  476.         
  477.         ScrollRect(&bounds, -2, 0, rgn);
  478.         
  479.         ClipRect(&hot);
  480.         MoveTo(bounds.right - offset, bounds.bottom - 3);
  481.         DrawString(string);
  482.         DrawString("\p • ");
  483.         ClipRect(&bounds);
  484.         
  485.         if ((offset += 2) >= widths[current]) {
  486.             current = (current+1) % count;
  487.             offset  = 0;
  488.             GetIndString(string, CreditID, current+1);
  489.         }
  490. #endif
  491.  
  492.         if (WaitNextEvent(mDownMask+keyDownMask+activMask+updateMask+osMask, &ev, 1, nil))
  493.             switch (ev.what) {
  494.             case activateEvt:
  495.                 if ((WindowPtr) ev.message != dlg)
  496.                     DoActivate((WindowPtr)ev.message, (ev.modifiers & activeFlag) != 0);
  497.                     
  498.                 break;
  499.     
  500.             case updateEvt:
  501.                 if ((WindowPtr) ev.message == dlg) {
  502.                     BeginUpdate(dlg);
  503.                     UpdtDialog(dlg, dlg->visRgn);
  504.                     EndUpdate(dlg);
  505.                 } else
  506.                     DoUpdate(DPtrFromWindowPtr((WindowPtr)ev.message));
  507.                 break;
  508.     
  509.             case kOSEvent:
  510.                 switch (ev.message & osEvtMessageMask) { /*high byte of message*/
  511.                 case 0x01000000:
  512.                         gInBackground = ((ev.message & resumeFlag) == 0);
  513.                 }
  514.                 if (!gInBackground)
  515.                     break;
  516.             default:
  517.                 DisposeDialog(dlg);
  518.                 
  519.                 dlg = nil;
  520.                 break;
  521.             }
  522.     }
  523. }
  524.  
  525. static void CenterWindow(DialogPtr dlg)
  526. {
  527.     Rect    *        screen;
  528.     short            hPos;
  529.     short            vPos;
  530.     
  531.     screen    =    &qd.screenBits.bounds;
  532.     hPos    =    screen->right+screen->left-dlg->portRect.right >> 1;
  533.     vPos    =    (screen->bottom-screen->top-dlg->portRect.bottom)/3;
  534.     vPos    +=    screen->top;
  535.     MoveWindow(dlg, hPos, vPos, true);
  536. }    
  537.  
  538. #ifdef RUNTIME
  539.  
  540. typedef long ICON[32];
  541. typedef struct    {
  542.     ICON    icon;
  543.     ICON    mask;
  544. } ICN_;
  545.  
  546. typedef short icm[12];
  547. typedef struct {
  548.     icm    icon;
  549.     icm     mask;
  550. } icm_;
  551.  
  552. static void PlotICN_(ICN_ * icon, Rect * within, IconMode mode)
  553. {
  554.     GrafPtr    port;
  555.     BitMap    bmap;
  556.     BitMap    mask;
  557.     PenState    ps;
  558.     Pattern    ltGray;
  559.     long    *    lg;
  560.     
  561.     GetPort(&port);
  562.     bmap.baseAddr        =    (Ptr) icon;
  563.     bmap.rowBytes        =    4;
  564.     bmap.bounds.top    =    0;
  565.     bmap.bounds.left    =    0;
  566.     bmap.bounds.bottom=    32;
  567.     bmap.bounds.right    =    32;
  568.     
  569.     mask = bmap;
  570.     mask.baseAddr        =    (Ptr) icon->mask;
  571.     
  572.     switch (mode)    {
  573.     case iconGray:
  574.         GetPenState(&ps);
  575.         PenMode(patXor);
  576.         lg     =  (long *)<Gray;
  577.         lg[0] =    0x11004400;
  578.         lg[1] =    lg[0];
  579.         PenPat(<Gray);
  580.         PaintRect(within);
  581.         CopyBits(&mask, &port->portBits, &mask.bounds, within, srcBic, nil);
  582.         PaintRect(within);
  583.         CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcOr, nil);
  584.         SetPenState(&ps);
  585.         break;
  586.     case iconHilited:
  587.         CopyBits(&mask, &port->portBits, &mask.bounds, within, srcOr, nil);
  588.         CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcXor, nil);
  589.         break;
  590.     default:
  591.         CopyBits(&mask, &port->portBits, &mask.bounds, within, srcBic, nil);
  592.         CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcXor, nil);
  593.         break;
  594.     }
  595. }
  596.  
  597. pascal void PlotResICN_(short id, Rect * within, IconMode mode)
  598. {
  599.     char        flags;
  600.     ICN_ **  icon;
  601.     
  602.     if (icon = (ICN_ **) GetResource('ICN#', id))    {
  603.         flags    =    HGetState((Handle) icon);
  604.         HLock((Handle) icon);
  605.         PlotICN_(*icon, within, mode);
  606.         HSetState((Handle) icon, flags);
  607.     }
  608. }
  609.  
  610. static void PlotMiniIcon(icm_ * icon, Rect * within)
  611. {
  612.     GrafPtr    port;
  613.     BitMap    bmap;
  614.     BitMap    mask;
  615.     
  616.     GetPort(&port);
  617.     bmap.baseAddr        =    (Ptr) icon;
  618.     bmap.rowBytes        =    2;
  619.     bmap.bounds.top    =    0;
  620.     bmap.bounds.left    =    0;
  621.     bmap.bounds.bottom=    12;
  622.     bmap.bounds.right    =    16;
  623.     
  624.     mask = bmap;
  625.     mask.baseAddr        =    (Ptr) icon->mask;
  626.     
  627.     CopyBits(&mask, &port->portBits, &mask.bounds, within, srcBic, nil);
  628.     CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcXor, nil);
  629. }
  630.  
  631. pascal void PlotResMiniIcon(short id, Rect * within)
  632. {
  633.     char        flags;
  634.     icm_ **  icon;
  635.     
  636.     if (icon = (icm_ **) GetResource('icm#', id))    {
  637.         flags    =    HGetState((Handle) icon);
  638.         HLock((Handle) icon);
  639.         PlotMiniIcon(*icon, within);
  640.         HSetState((Handle) icon, flags);
  641.     }
  642. }
  643.  
  644. typedef struct {
  645.       Handle  handle;     /* handle or procedure pointer for this item */
  646.       Rect    bounds;     /* display rectangle for this item */
  647.       char    type;       /* item type - 1 */
  648.       char    data[1];    /* length byte of data */
  649.  } DialogItem;
  650.  
  651. typedef struct {
  652.       short            max_index; /* number of items - 1 */
  653.       DialogItem    items[1]; /* first item in the array */
  654.  } **ItemListHandle;
  655.  
  656. pascal void Append_DITL(DialogPtr dialog, short item_list_ID)
  657. {
  658.     ItemListHandle append_item_list;    /* handle to DITL being appended */
  659.     DialogItem *    item;                /* pointer to item being appended */
  660.     ItemListHandle    dlg_item_list;       /* handle to DLOG's item list */
  661.     short                i;
  662.     short                sz;
  663.     
  664.     dlg_item_list = (ItemListHandle) ((DialogPeek)dialog)->items;
  665.     append_item_list = (ItemListHandle)GetResource('DITL', item_list_ID);
  666.     if (!append_item_list)
  667.       return;
  668.  
  669.    HLock((Handle)append_item_list);
  670.        
  671.     item = (*append_item_list)->items;
  672.     
  673.     for (i=0; i<=(*append_item_list)->max_index; ++i) {
  674.           switch (item->type & 0x7F) {
  675.         case ctrlItem + btnCtrl:
  676.         case ctrlItem + chkCtrl:
  677.         case ctrlItem + radCtrl:
  678.             item->handle = 
  679.                 (Handle)
  680.                     NewControl(
  681.                         (DialogPtr) dialog, &item->bounds,
  682.                         (StringPtr)item->data,
  683.                         true, 0, 0, 1,
  684.                         item->type & 0x03,
  685.                         0);
  686.             break;
  687.  
  688.         case ctrlItem + resCtrl :
  689.             item->handle = (Handle)GetNewControl(*(int*)(item->data + 1), (DialogPtr) dialog);
  690.             (**(ControlHandle)item->handle).contrlRect = item->bounds;
  691.             break;
  692.  
  693.         case statText :
  694.         case editText :
  695.             PtrToHand(item->data + 1, &item->handle, item->data[0]);
  696.             break;
  697.  
  698.         case iconItem :
  699.             item->handle = GetIcon(*(int*)(item->data + 1));
  700.             break;
  701.  
  702.         case picItem :
  703.             item->handle = (Handle)GetPicture(*(int*)(item->data + 1));
  704.             break;
  705.  
  706.         default :
  707.             item->handle = NULL;
  708.           }
  709.  
  710.       sz = (item->data[0] + 1) & 0xFFFE;
  711.       item = (DialogItem *)((char*)item + sz + sizeof(DialogItem));
  712.    }
  713.  
  714.       PtrAndHand(
  715.         (*append_item_list)->items,
  716.       (Handle)dlg_item_list,
  717.       GetHandleSize((Handle) append_item_list) - 2);
  718.    (*dlg_item_list)->max_index += (*append_item_list)->max_index + 1;
  719.    HUnlock((Handle) append_item_list);
  720.    ReleaseResource((Handle) append_item_list);
  721. }
  722.  
  723. pascal void Shorten_DITL(DialogPtr dialog, short shorten)
  724. {
  725.     DialogItem *    item;                /* pointer to item being appended */
  726.     ItemListHandle    dlg_item_list;       /* handle to DLOG's item list */
  727.     short                i;
  728.     short                sz;
  729.     short                restSize = -1;
  730.     
  731.     dlg_item_list = (ItemListHandle) ((DialogPeek)dialog)->items;
  732.  
  733.    HLock((Handle)dlg_item_list);
  734.        
  735.     item         = (*dlg_item_list)->items;
  736.     shorten     = (*dlg_item_list)->max_index - shorten;
  737.     
  738.     for (i=0; i<=(*dlg_item_list)->max_index; ++i) {
  739.         if (i > shorten)
  740.             switch (item->type & 0x7F) {
  741.             case ctrlItem + btnCtrl:
  742.             case ctrlItem + chkCtrl:
  743.             case ctrlItem + radCtrl:
  744.             case ctrlItem + resCtrl :
  745.                 DisposeControl((ControlHandle) item->handle);
  746.                 break;
  747.     
  748.             case statText :
  749.             case editText :
  750.                 DisposeHandle(item->handle);
  751.                 break;
  752.     
  753.             case iconItem :
  754.             case picItem :
  755.                 ReleaseResource(item->handle);
  756.                 break;
  757.     
  758.             default :
  759.                 break;
  760.             }
  761.  
  762.       sz = (item->data[0] + 1) & 0xFFFE;
  763.       item = (DialogItem *)((char*)item + sz + sizeof(DialogItem));
  764.         
  765.         if (i == shorten)
  766.             restSize = (char *) item - (char *) *dlg_item_list;
  767.    }
  768.  
  769.      if (restSize >= 0) {
  770.           SetHandleSize((Handle) dlg_item_list, restSize);
  771.         
  772.        (*dlg_item_list)->max_index = shorten;
  773.     }
  774.     
  775.    HUnlock((Handle) dlg_item_list);
  776. }
  777.  
  778. pascal short Count_DITL(DialogPtr dialog)
  779. {
  780.     return (*(ItemListHandle) ((DialogPeek)dialog)->items)->max_index + 1;
  781. }
  782.  
  783. #endif
  784.  
  785. pascal void Separator(DialogPtr dlg, short item)
  786. {
  787.     short        kind;
  788.     Handle    h;
  789.     Rect        r;
  790.     
  791.     PenPat(&qd.gray);
  792.     GetDItem(dlg, item, &kind, &h, &r);
  793.     FrameRect(&r);
  794.     PenPat(&qd.black);
  795. }
  796.  
  797. static DPtr        Documents[50];
  798. static short    DocCount = 0;
  799.  
  800. pascal void RegisterDocument(DPtr doc)
  801. {
  802.     Documents[DocCount++] = doc;
  803. }
  804.  
  805. pascal void UnregisterDocument(DPtr doc)
  806. {
  807.     short    i,j;
  808.     
  809.     for (i = 0, j = 0; i < DocCount; ++i)
  810.         if (Documents[i] != doc)
  811.             Documents[j++] = Documents[i];
  812.     
  813.     DocCount = j;
  814. }
  815.  
  816. pascal void SetupWindowMenu()
  817. {
  818.     short            i;
  819.     short            item = 0;
  820.     WindowPtr    front;
  821.      WindowPeek    aWindow;
  822.     WindowPeek    nextWindow;
  823.     MenuHandle    menu;
  824.     Str255        name;
  825.     int             needsSeparator = 0;
  826.     
  827.     DisposeMenu(myMenus[windowM]);
  828.     menu = myMenus[windowM]    = GetMenu(windowID);
  829.     
  830.     front = FrontWindow();
  831.     
  832.     for (i = 0; i < DocCount; ++i)
  833.         if (Documents[i]->kind != kDocumentWindow) {
  834.             AppendMenu(menu, "\px");
  835.             GetWTitle(Documents[i]->theWindow, name);
  836.             SetMenuItemText(menu, ++item, name);
  837.             
  838.             if (!((WindowPeek) Documents[i]->theWindow)->visible)
  839.                 SetItemStyle(menu, item, italic);
  840.             else if (Documents[i]->theWindow == front)
  841.                 SetItemMark(menu, item, checkMark);
  842.             
  843.             EnableItem(menu, item);
  844.             needsSeparator = 1;
  845.         }
  846.     
  847.     for (i = 0; i < DocCount; ++i)
  848.         if (Documents[i]->kind == kDocumentWindow) {
  849.             if (needsSeparator && needsSeparator < 2) {
  850.                 AppendMenu(menu, "\p-(");
  851.                 ++item;
  852.             }
  853.             
  854.             AppendMenu(menu, "\px");
  855.             GetWTitle(Documents[i]->theWindow, name);
  856.             SetMenuItemText(menu, ++item, name);
  857.             
  858.             if (!((WindowPeek) Documents[i]->theWindow)->visible)
  859.                 SetItemStyle(menu, item, Documents[i]->dirty ? underline + italic : italic);
  860.             else {
  861.                 if (Documents[i]->dirty)
  862.                     SetItemStyle(menu, item, underline);
  863.                 if (Documents[i]->theWindow == front)
  864.                     SetItemMark(menu, item, checkMark);
  865.             }
  866.             
  867.             EnableItem(menu, item);
  868.             needsSeparator = 2;
  869.         }
  870.     
  871.     for (aWindow = (WindowPeek) FrontWindow(); aWindow; aWindow = nextWindow) {
  872.         nextWindow = aWindow->nextWindow;
  873.         if (aWindow->visible && !Ours((WindowPtr) aWindow)) {
  874.             if (needsSeparator && needsSeparator < 3) {
  875.                 AppendMenu(menu, "\p-(");
  876.                 ++item;
  877.             }
  878.             
  879.             AppendMenu(menu, "\px");
  880.             GetWTitle((WindowPtr) aWindow, name);
  881.             SetMenuItemText(menu, ++item, name);
  882.             
  883.             if ((WindowPtr) aWindow == front)
  884.                 SetItemMark(menu, item, checkMark);
  885.             
  886.             EnableItem(menu, item);
  887.             needsSeparator = 3;
  888.         }
  889.     }
  890. }
  891.  
  892. static void AnointWindow(WindowPtr win)
  893. {
  894.     if (!((WindowPeek) win)->visible)
  895.         ShowWindow(win);
  896.     SelectWindow(win);
  897. }
  898.  
  899. pascal void DoSelectWindow(short item)
  900. {
  901.     short            i;
  902.      WindowPeek    aWindow;
  903.     WindowPeek    nextWindow;
  904.     MenuHandle    menu;
  905.     int             needsSeparator = 0;
  906.     
  907.     menu = myMenus[windowM];
  908.     
  909.     for (i = 0; i < DocCount; ++i)
  910.         if (Documents[i]->kind != kDocumentWindow) {
  911.             if (!--item) {
  912.                 AnointWindow(Documents[i]->theWindow);
  913.                 
  914.                 return;
  915.             }
  916.             needsSeparator = 1;
  917.         }
  918.     
  919.     for (i = 0; i < DocCount; ++i)
  920.         if (Documents[i]->kind == kDocumentWindow) {
  921.             if (needsSeparator && needsSeparator < 2) {
  922.                 --item;
  923.             }
  924.             
  925.             if (!--item) {
  926.                 AnointWindow(Documents[i]->theWindow);
  927.                 
  928.                 return;
  929.             }
  930.             
  931.             needsSeparator = 2;
  932.         }
  933.     
  934.     for (aWindow = (WindowPeek) FrontWindow(); aWindow; aWindow = nextWindow) {
  935.         nextWindow = aWindow->nextWindow;
  936.         if (aWindow->visible && !Ours((WindowPtr) aWindow)) {
  937.             if (needsSeparator && needsSeparator < 3) {
  938.                 --item;
  939.             }
  940.             
  941.             if (!--item) {
  942.                 AnointWindow((WindowPtr) aWindow);
  943.                 
  944.                 return;
  945.             }
  946.             
  947.             needsSeparator = 3;
  948.         }
  949.     }
  950. }
  951.  
  952. /* Borrowed from tech note 263 */
  953.  
  954. #define kKosherModifiers    0x0E00        // We keep only option & shift
  955. #define kMaskVirtualKey     0x0000FF00     // get virtual key from event message
  956.                                            // for KeyTrans
  957. #define kUpKeyMask          0x0080
  958. #define kShiftWord          8              // we shift the virtual key to mask it
  959.                                            // into the keyCode for KeyTrans
  960. #define kMaskASCII1         0x00FF0000     // get the key out of the ASCII1 byte
  961. #define kMaskASCII2         0x000000FF     // get the key out of the ASCII2 byte
  962.  
  963. pascal Boolean WeirdChar(const EventRecord * ev, short modifiers, char ch)
  964. {
  965.       short    keyCode;
  966.       long     virtualKey, keyInfo, lowChar, highChar, state, keyCId;
  967.       Handle   hKCHR;
  968.     Ptr         KCHRPtr;
  969.  
  970.     if ((ev->what == keyDown) || (ev->what == autoKey)) {
  971.  
  972.         // see if the command key is down.  If it is, find out the ASCII
  973.         // equivalent for the accompanying key.
  974.  
  975.         if ((ev->modifiers & 0xFF00) == modifiers) {
  976.  
  977.             virtualKey     = (ev->message & kMaskVirtualKey) >> kShiftWord;
  978.             keyCode          = (ev->modifiers & kKosherModifiers & ~modifiers) | virtualKey;
  979.             state           = 0;
  980.  
  981.             hKCHR            = nil;  /* set this to nil before starting */
  982.              KCHRPtr         = (Ptr)GetEnvirons(smKCHRCache);
  983.  
  984.             if ( !KCHRPtr ) {
  985.                 keyCId     =    GetScript((short) GetEnvirons(smKeyScript), smScriptKeys);
  986.                 hKCHR        =    GetResource('KCHR', (short) keyCId);
  987.                 KCHRPtr    = *hKCHR;
  988.             }
  989.  
  990.             if (KCHRPtr) {
  991.                 keyInfo = KeyTrans(KCHRPtr, keyCode, &state);
  992.                 if (hKCHR)
  993.                     ReleaseResource(hKCHR);
  994.             } else
  995.                 keyInfo = ev->message;
  996.  
  997.             lowChar =  keyInfo &  kMaskASCII2;
  998.             highChar = (keyInfo & kMaskASCII1) >> 16;
  999.             if (lowChar == ch || highChar == ch)
  1000.                 return true;
  1001.  
  1002.         }  // end the command key is down
  1003.     }  // end key down event
  1004.  
  1005.     return false;
  1006. }
  1007.